home *** CD-ROM | disk | FTP | other *** search
- /*
- * main.c --
- *
- * The main program for Sprite: initializes modules and creates
- * system processes. Also creates a process to run the Init program.
- *
- * Copyright 1986 Regents of the University of California
- * All rights reserved.
- */
-
- #ifndef lint
- static char rcsid[] = "$Header: /cdrom/src/kernel/Cvsroot/kernel/main/sun4.md/mainInit.c,v 9.12 92/08/10 20:44:18 mgbaker Exp $ SPRITE (Berkeley)";
- #endif /* !lint */
-
- #include <sprite.h>
- #include <dbg.h>
- #include <dev.h>
- #include <net.h>
- #include <fs.h>
- #include <fsutil.h>
- #include <proc.h>
- #include <prof.h>
- #include <recov.h>
- #include <rpc.h>
- #include <sched.h>
- #include <sig.h>
- #include <sync.h>
- #include <sys.h>
- #include <timer.h>
- #include <vm.h>
- #include <machMon.h>
- #include <devAddrs.h>
- #include <mach.h>
- #include <stdlib.h>
- #include <main.h>
- #include <stdio.h>
- #include <bstring.h>
- #include <string.h>
- #include <dump.h>
- #include <fsrecov.h>
-
- static void Init _ARGS_((void));
-
- /*
- * Pathname of the Init program.
- */
- #define INIT "cmds/initsprite"
-
- int main_PrintInitRoutines = FALSE;/* print out each routine as it's called. */
-
- int main_PanicOK = 0; /* Set to 1 if it's OK to panic. */
-
- /*
- *----------------------------------------------------------------------
- *
- * main --
- *
- * All kernel modules are initialized by calling their *_Init()
- * routines. In addition, kernel processes are created to
- * handle virtual memory and rpc-specific stuff. The last process
- * created runs the `init' program.
- *
- * Results:
- * None.
- *
- * Side effects:
- * The whole system is initialized.
- *
- *----------------------------------------------------------------------
- */
-
- void
- main()
- {
- Proc_PID pid;
- int i;
-
- /*
- * Initialize variables specific to a given kernel.
- * IMPORTANT: Only variable assignments and nothing else can be
- * done in this routine.
- */
- Main_InitVars();
-
- /*
- * Initialize machine dependent info. MUST BE CALLED HERE!!!.
- */
- Mach_Init();
- Sync_Init();
-
- /*
- * Initialize the debugger.
- */
- Dbg_Init();
-
- /*
- * Initialize the system module, particularly the fact that there is an
- * implicit DISABLE_INTR on every processor.
- */
- if (main_PrintInitRoutines) {
- Mach_MonPrintf("Calling Sys_Init().\n");
- }
- Sys_Init();
-
- /*
- * Now allow memory to be allocated by the "Vm_BootAlloc" call. Memory
- * can be allocated by this method until "Vm_Init" is called. After this
- * then the normal memory allocator must be used.
- */
- if (main_PrintInitRoutines) {
- Mach_MonPrintf("Calling Vm_BootInit().\n");
- }
- Vm_BootInit();
-
- /*
- * Initialize all devices.
- */
- if (main_PrintInitRoutines) {
- Mach_MonPrintf("Calling Dev_Init().\n");
- }
- Dev_Init();
-
- /*
- * Initialize the mappings of keys to call dump routines.
- * Must be after Dev_Init.
- */
- if (main_DoDumpInit) {
- if (main_PrintInitRoutines) {
- Mach_MonPrintf("Calling Dump_Init().\n");
- }
- Dump_Init();
- }
-
- /*
- * Initialize the timer, signal, process, scheduling and synchronization
- * modules' data structures.
- */
- if (main_PrintInitRoutines) {
- Mach_MonPrintf("Calling Proc_Init().\n");
- }
- Proc_Init();
- if (main_PrintInitRoutines) {
- Mach_MonPrintf("Calling Sync_LockStatInit().\n");
- }
- Sync_LockStatInit();
- if (main_PrintInitRoutines) {
- Mach_MonPrintf("Calling Timer_Init().\n");
- }
- Timer_Init();
- if (main_PrintInitRoutines) {
- Mach_MonPrintf("Calling Sig_Init().\n");
- }
- Sig_Init();
- if (main_PrintInitRoutines) {
- Mach_MonPrintf("Calling Sched_Init().\n");
- }
- Sched_Init();
-
- /*
- * Sys_Printfs are not allowed before this point.
- */
- main_PanicOK++;
- printf("Sprite kernel: %s\n", SpriteVersion());
-
- /*
- * Set up bins for the memory allocator.
- */
- if (main_PrintInitRoutines) {
- Mach_MonPrintf("Calling Fs_Bin\n");
- }
- Fs_Bin();
- if (main_PrintInitRoutines) {
- Mach_MonPrintf("Calling Net_Bin\n");
- }
- Net_Bin();
-
- /*
- * Initialize virtual memory. After this point must use the normal
- * memory allocator to allocate memory. If you use Vm_BootAlloc then
- * will get a panic into the debugger.
- */
- if (main_PrintInitRoutines) {
- Mach_MonPrintf("Calling Vm_Init\n");
- }
- Vm_Init();
-
- /*
- * malloc can be called from this point on.
- */
-
- /*
- * Initialize the main process. Must be called before any new
- * processes are created.
- * Dependencies: Proc_InitTable, Sched_Init, Vm_Init, Mem_Init
- */
- if (main_PrintInitRoutines) {
- Mach_MonPrintf("Calling Proc_InitMainProc\n");
- }
- Proc_InitMainProc();
-
- /*
- * Initialize the network and the routes. It would be nice if we
- * could call Net_Init earlier so that we can use the debugger earlier
- * but we must call Vm_Init first. VM could be changed so that we
- * could move the call earlier however.
- */
- if (main_PrintInitRoutines) {
- Mach_MonPrintf("Calling Net_Init\n");
- }
- Net_Init();
- if (main_PrintInitRoutines) {
- Mach_MonPrintf("Calling Net_RouteInit\n");
- }
- Net_RouteInit();
-
- /*
- * Enable server process manager.
- */
- if (main_PrintInitRoutines) {
- Mach_MonPrintf("Calling Proc_ServerInit\n");
- }
- Proc_ServerInit();
-
- /*
- * Initialize the recovery module. Do before Rpc and after Vm_Init.
- */
- if (main_PrintInitRoutines) {
- Mach_MonPrintf("Calling Recov_Init\n");
- }
- Recov_Init();
-
- /*
- * Initialize the data structures for the Rpc system. This uses
- * Vm_RawAlloc to so it must be called after Vm_Init.
- * Dependencies: Timer_Init, Vm_Init, Net_Init, Recov_Init
- */
- if (main_PrintInitRoutines) {
- Mach_MonPrintf("Calling Rpc_Init\n");
- }
- Rpc_Init();
-
- /*
- * Configure devices that may or may not exist. This needs to be
- * done after Proc_InitMainProc because the initialization routines
- * use SetJump which uses the proc table entry for the main process.
- */
- if (main_PrintInitRoutines) {
- Mach_MonPrintf("Calling Dev_Config\n");
- }
- Dev_Config();
-
- /*
- * Initialize profiling after the timer and vm stuff is set up.
- * Dependencies: Timer_Init, Vm_Init
- */
- if (main_DoProf) {
- Prof_Init();
- }
- /*
- * Allow interrupts from now on.
- */
- if (main_PrintInitRoutines) {
- Mach_MonPrintf("Enabling interrupts\n");
- }
- Mach_MonStartNmi();
- ENABLE_INTR();
-
- if (main_Debug) {
- DBG_CALL;
- }
-
- /*
- * Initialize the fs recovery stuff.
- */
- if (main_PrintInitRoutines && recov_Transparent) {
- Mach_MonPrintf("Calling Fsrecov_InitState.\n");
- }
- if (recov_Transparent) {
- Fsrecov_InitState();
- }
-
- /*
- * Initialize dir op log recovery stuff.
- */
- if (main_PrintInitRoutines && recov_Transparent) {
- Mach_MonPrintf("Calling Fsrecov_DirOpInit.\n");
- }
- if (recov_Transparent) {
- Fsrecov_DirOpInit();
- }
-
-
- /*
- * Sleep for a few seconds to calibrate the idle time ticks.
- */
- Sched_TimeTicks();
-
- /*
- * Start profiling, if desired.
- */
- if (main_DoProf) {
- (void) Prof_Start();
- }
-
- /*
- * Do an initial RPC to get a boot timestamp. This allows
- * servers to detect when we crash and reboot. This will set the
- * system clock too, although rdate is usually done from user level later.
- */
- if (main_PrintInitRoutines) {
- Mach_MonPrintf("Call Rpc_Start\n");
- }
- Rpc_Start();
-
- /*
- * Initialize the file system.
- */
- if (main_PrintInitRoutines) {
- Mach_MonPrintf("Call Fs_Init\n");
- }
- Fs_Init();
-
- /*
- * Before starting up any more processes get a current directory
- * for the main process. Subsequent new procs will inherit it.
- */
- if (main_PrintInitRoutines) {
- Mach_MonPrintf("Call Fs_ProcInit\n");
- }
- Fs_ProcInit();
- if (main_PrintInitRoutines) {
- Mach_MonPrintf("Bunch of call funcs\n");
- }
- /*
- * Start the clock daemon and the routine that opens up the swap directory.
- */
- Proc_CallFunc(Vm_Clock, (ClientData) NIL, 0);
- Proc_CallFunc(Vm_OpenSwapDirectory, (ClientData) NIL, 0);
-
- /*
- * Start the process that synchronizes the filesystem caches
- * with the data kept on disk.
- */
- Proc_CallFunc(Fsutil_SyncProc, (ClientData) NIL, 0);
-
- /*
- * Create a few RPC server processes and the Rpc_Daemon process which
- * will create more server processes if needed.
- */
- if (main_NumRpcServers > 0) {
- for (i=0 ; i<main_NumRpcServers ; i++) {
- (void) Rpc_CreateServer((int *) &pid);
- }
- }
- (void) Proc_NewProc((Address) Rpc_Daemon, PROC_KERNEL, FALSE, &pid,
- "Rpc_Daemon", FALSE);
- if (main_PrintInitRoutines) {
- Mach_MonPrintf("Creating Proc server procs\n");
- }
-
- /*
- * Create processes to execute functions.
- */
- (void) Proc_ServerProcCreate(FSCACHE_MAX_CLEANER_PROCS +
- VM_MAX_PAGE_OUT_PROCS);
-
- /*
- * Create a recovery process to monitor other hosts. Can't use
- * Proc_CallFunc's to do this because they can be used up waiting
- * for page faults against down servers. (Alternatively the VM
- * code could be fixed up to retry page faults later instead of
- * letting the Proc_ServerProc wait for recovery.)
- */
- (void) Proc_NewProc((Address) Recov_Proc, PROC_KERNEL, FALSE, &pid,
- "Recov_Proc", FALSE);
- /*
- * Set up process migration recovery management.
- */
- if (main_PrintInitRoutines) {
- Mach_MonPrintf("Calling Proc_MigInit\n");
- }
- Proc_MigInit();
-
- /*
- * Call the routine to start test kernel processes.
- */
-
- if (main_PrintInitRoutines) {
- Mach_MonPrintf("Calling Main_HookRoutine\n");
- }
- Main_HookRoutine();
-
- /*
- * Print out the amount of memory used.
- */
- printf("MEMORY %d bytes allocated for kernel\n",
- vmMemEnd - mach_KernStart);
- /*
- * Start up the first user process.
- */
- if (main_PrintInitRoutines) {
- Mach_MonPrintf("Creating Init\n");
- }
- (void) Proc_NewProc((Address) Init, PROC_KERNEL, FALSE, &pid, "Init",
- FALSE);
-
- (void) Sync_WaitTime(time_OneYear);
- printf("Main exiting\n");
- Proc_Exit(0);
- }
-
-
- /*
- *----------------------------------------------------------------------
- *
- * Init --
- *
- * This routine execs the init program.
- *
- * Results:
- * This routine only returns an error if the exec failed.
- *
- * Side effects:
- * The current process image is overlayed by the init process.
- *
- *----------------------------------------------------------------------
- */
- static void
- Init()
- {
- char *initArgs[10];
- ReturnStatus status;
- char argBuffer[100];
- int argc;
- Fs_Stream *dummy;
- char bootCommand[103];
- char *ptr;
- int i;
- int argLength;
-
- if (main_PrintInitRoutines) {
- Mach_MonPrintf("In Init\n");
- }
- bzero(bootCommand, 103);
- argc = Mach_GetBootArgs(8, 100, &(initArgs[2]), argBuffer);
- if (argc > 0) {
- argLength = (((int) initArgs[argc+1]) + strlen(initArgs[argc+1]) +
- 1 - ((int) argBuffer));
- } else {
- argLength = 0;
- }
- if (argLength > 0) {
- initArgs[1] = "-b";
- ptr = bootCommand;
- for (i = 0; i < argLength; i++) {
- if (argBuffer[i] == '\0') {
- *ptr++ = ' ';
- } else {
- *ptr++ = argBuffer[i];
- }
- }
- bootCommand[argLength] = '\0';
- initArgs[2] = bootCommand;
- initArgs[argc + 2] = (char *) NIL;
- } else {
- initArgs[1] = (char *) NIL;
- }
- if (main_AltInit != 0) {
- initArgs[0] = main_AltInit;
- printf("Execing \"%s\"\n", initArgs[0]);
- status = Proc_KernExec(initArgs[0], initArgs);
- printf( "Init: Could not exec %s status %x.\n",
- initArgs[0], status);
- }
- status = Fs_Open(INIT,FS_EXECUTE | FS_FOLLOW, FS_FILE, 0, &dummy);
- if (status != SUCCESS) {
- printf("Can't open %s <0x%x>\n", INIT,status);
- }
- initArgs[0] = INIT;
- status = Proc_KernExec(initArgs[0], initArgs);
- printf( "Init: Could not exec %s status %x.\n",
- initArgs[0], status);
- Proc_Exit(1);
- }
-
-